home *** CD-ROM | disk | FTP | other *** search
- /* Next available MSG number is 20 */
-
- /*
-
- TOWER.CC
-
- Copyright (C) 1994 by Autodesk, Inc.
-
- Permission to use, copy, modify, and distribute this software in
- object code form for any purpose and without fee is hereby granted,
- provided that the above copyright notice appears in all copies and
- that both that copyright notice and the limited warranty and
- restricted rights notice below appear in all supporting
- documentation.
-
- AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
- AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
- DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
- UNINTERRUPTED OR ERROR FREE.
-
- Use, duplication, or disclosure by the U.S. Government is subject to
- restrictions set forth in FAR 52.227-19 (Commercial Computer
- Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
- (Rights in Technical Data and Computer Software), as applicable.
-
- .
-
- Tower of Hanoi in C++ for the Rx/ADS environment
-
- Implemented by John Lynch December 1988
- Converted to Arx ADS by Cameron Reid Fetbruary 11, 1994
-
- This is basically a translation of tower.c written by
- John Lynch.
-
- This file implements the Tower of Hanoi problem. It is as
- specified in the rules:
-
- 1. Only one disc may be moved at a time.
- 2. No disc may be placed on top of a smaller one.
-
- The only incompatibility with the original is that the universe
- will not come to an end when this function completes (however, if
- you run it with the specified number of discs, 64, the protons may
- decay before it's done).
-
- One defines the tower with the command TOWER, which asks for the
- number of discs. Scaling is automatic, as is clearing away of any
- previous execution. Once the tower is defined, the solution may
- be accomplished with the command SOLVE.
-
- The solution function, TRANSFER, is as given in Winston and Horn,
- "LISP", second edition, pp. 112-114.
-
-
- */
-
- #include <stdlib.h>
- #include <iostream.h>
- #include <string.h>
- #include "rxdefs.h"
- #include "adslib.h"
- #include <stdio.h>
-
-
- #define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
-
-
- /* ADS Function Table structure */
- typedef struct {
- char *name;
- int (*fptr)();
- } ftblent;
-
-
- int funcLoad (void);
- int funcUnload (void);
- int doFun (void);
-
-
- extern "C" {
- AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg,void * pkt);
- }
-
- /* Local functions */
- static int loadfuncs _((void));
- static int dofun _((void));
- static int tower2 _((void));
- static int solve2 _((void));
- #ifdef __ZTC__
- static int movedisc _((int from, int to));
- static int transfer _((int from, int to, int spare, int n));
- #else
- static int movedisc _((short from, short to));
- static int transfer _((short from, short to, short spare, short n));
- #endif
-
-
- /* Table of ADS functions */
- ftblent exfun[] = {
- {"C:TOWER2", tower2},
- {"C:SOLVE2", solve2},
- };
-
- /* For convenience, make the global variables the same as in the LISP
- version */
-
- int nrings = 0, /* Number of rings */
- before = 0, /* Whether or not we have run before */
- armed = 0; /* Set if we are ready to solve */
-
- ads_real bthick = 1.0, /* Base thickness */
- rthick = 1.0, /* Ring thickness */
- smring = 1.5, /* Smallest ring */
- ringinc = 1.0, /* Ring size increment */
- postdia = 0.5, /* Post diameter */
- airspace = 0.1, /* Airspace */
- rspace = 1.1, /* Total ring space */
- postposx[3],
- postposy;
-
-
- /* The postlist structure is used to hold the disks */
- struct disk {
- struct disk *next;
- short color;
- ads_real r;
- ads_name diskname;
- } *disks;
-
- struct postlist {
- struct disk *top;
- short count;
- } postl[3];
-
- /* to keep track of stuff for cleanup */
-
- /* funcLoad -- Register (or define) external functions with AutoLISP */
- int
- funcLoad()
- {
- if (!ads_defun(/*MSG0*/"C:TOWER2", 0)) /* tower2 command has id 0 */
- return 0;
- if (!ads_defun(/*MSG0*/"C:SOLVE2", 1)) /* solve2 command has id 1 */
- return 0;
-
- ads_printf(/*MSG17*/"\
- Use tower2 to initialize, and solve2 to solve the tower\n");
-
- return 1;
- }
-
-
- /* Handle setup of tower */
-
- static int
- tower2()
- {
- ads_real lring; /* largest ring diameter */
- int a, i;
- ads_real bwidth, blength; /* width and length of base */
- ads_real x, y, z, r;
- struct resbuf genrb;
- ads_point pt1, pt2, pt3, pt4;
- struct resbuf *bufp;
- ads_name ename;
- short color;
-
- bthick = rthick = ringinc = postdia = 1.0;
- smring = 1.5;
- airspace = 0.1;
- rspace = 1.1;
-
- /* Disallow null, zero and negative responses. */
- ads_initget(7, NULL);
- ads_getint(/*MSG18*/"Enter number of rings: ", &nrings);
-
- lring = smring + (nrings * ringinc);
-
- /* reset from possible previous run */
- postl[0].top = postl[1].top = postl[2].top = NULL;
- postl[0].count = postl[1].count = postl[2].count = 0;
-
- disks = (struct disk *) malloc ((nrings + 1) * (sizeof (struct disk)));
-
- rspace = rthick + airspace; /* Actual ring spacing */
-
- /* set up the appropriate environment variables */
- genrb.restype = RTSHORT;
- genrb.resval.rint = 0;
- ads_setvar(/*MSG0*/"blipmode", &genrb);
- ads_setvar(/*MSG0*/"cmdecho", &genrb);
- ads_setvar(/*MSG0*/"fillmode", &genrb);
- color = 0;
-
- if (before) {
- // TBD
- // ads_setview(origin);
- while (ads_entlast( ename) == RTNORM)
- ads_entdel( ename);
- }
-
- /* Draw the base */
- bwidth = lring + 2 * postdia;
- blength = 3 * (postdia + lring) + postdia;
- pt1[X] = pt1[Y] = 0.0;
- pt2[Y] = pt4[Y] = bwidth;
- pt3[X] = pt4[X] = blength;
- pt2[X] = pt3[Y] = 0.0;
- bufp = ads_buildlist( RTDXF0, "SOLID", 62, color, 39, bthick,
- 10, pt1, 11, pt2, 12, pt3, 13, pt4, 0);
- ads_entmake(bufp);
-
- /* Draw the posts */
- x = postdia + lring;
- y = lring / 2 + postdia;
- postposx[0] = y;
- postposx[1] = y + x;
- postposx[2] = y + x + x;
-
- postposy = postdia + lring / 2;
-
- pt1[Y] = postposy;
-
- for (i = 0; i < 3; i++) {
- pt1[X] = postposx[i];
- bufp = ads_buildlist( RTDXF0, "CIRCLE", 62, color,
- 39, (nrings + 1) * rspace,
- 10, pt1, 40, postdia, 0);
- ads_entmake(bufp);
- }
- bthick += airspace; /* Offset position of lowest ring */
-
- // TBD
- // ads_setview( oneoneone);
-
- /* Draw the rings, placing them on the first post initially */
- pt1[X] = y;
- pt1[Y] = postposy;
-
- a = 6;
- z = bthick;
- r = lring / 2;
- for (i = 1; i <= nrings; i++) {
- pt1[Z] = z;
- disks[i].color = a%6+1;
-
- bufp = ads_buildlist( RTDXF0, "CIRCLE", 62, disks[i].color,
- 39, rthick, 10, pt1, 40, r, 0);
- ads_entmake(bufp);
- ads_entlast(disks[i].diskname);
-
- /* Hang it on the postlist */
- disks[i].r = r;
- disks[i].next = postl[0].top;
-
- postl[0].top = &disks[i];
- postl[0].count++;
-
- r -= ringinc / 2;
- z += rspace;
- a++;
- }
-
- before = nrings + 4;
-
- genrb.restype = RTSHORT;
- genrb.resval.rint = 0;
- ads_setvar(/*MSG0*/"cmdecho", &genrb);
-
- armed = TRUE;
- ads_retvoid();
-
- return TRUE;
- }
-
- /* Solve the tower problem. */
- static int
- solve2()
- {
- if (!armed) {
- ads_printf(/*MSG19*/"You must tower2 before solving\n");
- return TRUE;
- } else
- armed = FALSE;
-
- transfer(1, 2, 3, nrings);
- ads_redraw(NULL, 0);
- ads_retvoid();
- return TRUE;
- }
-
- static int
- movedisc(short from, short to)
- {
- struct disk *lfrom, *lto;
- ads_point pt;
- ads_name ename;
- resbuf *bufp;
-
- /* Get the current heads of the to and from lists */
- lfrom = postl[from - 1].top;
- lto = postl[to - 1].top;
-
- /* Remove this disk from the head of the from list */
- postl[from - 1].top = lfrom->next;
- postl[from - 1].count--;
-
- /* Remove this disk from the drawing */
- ads_entdel( lfrom->diskname);
-
- pt[X] = postposx[to - 1];
- pt[Y] = postposy;
- pt[Z] = bthick + postl[to-1].count * rspace;
- bufp = ads_buildlist( RTDXF0, "CIRCLE", 62, lfrom->color, 39, rthick,
- 10, pt, 40, lfrom->r, 0);
- ads_entmake( bufp);
- ads_entlast( lfrom->diskname);
-
- /* Place the disk on the top of the to list */
- lfrom->next = lto;
- postl[to - 1].top = lfrom;
- postl[to - 1].count++;
-
- return TRUE;
- }
-
-
- static int transfer(short from, short to, short spare, short n)
- {
- if (n == 0)
- return TRUE;
- else if (n == 1)
- movedisc(from, to);
- else {
- transfer(from, spare, to, n - 1);
- movedisc(from, to);
- transfer(spare, to, from, n - 1);
- }
- return TRUE;
- }
-
-
- /******************************************************************************/
- /*.doc funclUnload(internal) */
- /*+
- This function is called to undefine all function names in the ADS
- function table. Each named function will be removed from the
- AutoLISP hash table.
- -*/
- /******************************************************************************/
- int
- /*FCN*/funcUnload()
- {
- int i;
-
- /* Undefine each function we defined */
-
- for (i = 0; i < ELEMENTS(exfun); i++) {
- ads_undef(exfun[i].name,i);
- }
-
- return RTNORM;
- }
-
- /******************************************************************************/
- /*.doc doFun(internal) */
- /*+
- This function is called to invoke the function which has the
- registerd function code that is obtained from ads_getfuncode. The
- function will return RTERROR if the function code is invalid, or
- RSERR if the invoked function fails to return RTNORM. The value
- RSRSLT will be returned if the function code is valid and the
- invoked subroutine returns RTNORM.
- -*/
- /******************************************************************************/
- int
- /*FCN*/doFun()
- {
- int val;
- int rc;
-
- ads_retvoid();
-
- if ((val = ads_getfuncode()) < 0 || val > ELEMENTS(exfun))
- return RTERROR;
-
- rc = (*exfun[val].fptr)();
-
- return ((rc == RTNORM) ? RSRSLT:RSERR);
- }
-
-
- AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg, void* ptr)
- {
-
- if (ptr != NULL) {
- // We have been handed some kind of object
- // but we aren't going to do anything with it.
- }
-
- switch(msg) {
- case AcRx::kInitAppMsg:
- break;
- case AcRx::kInvkSubrMsg:
- doFun();
- break;
- case AcRx::kLoadADSMsg:
- funcLoad();
- break;
- case AcRx::kUnloadADSMsg:
- funcUnload();
- ads_printf(/*MSG2*/"Unloading.\n");
- break;
- case AcRx::kUnloadAppMsg:
- default:
- break;
- }
- return AcRx::kRetOK;
- }
-
-
-